package game.sprite;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;


/**
 * A class to allow the game to be played on a moveable background. Can
 * transform all coordinates in the game based
 * on its current position.
 * 
 * @author Ben Schwab
 * 
 */
public abstract class Background {

    private static int ourDrawX;
    private static int ourDrawY;
    private int myDrawWidth;
    private int myDrawHeight;
    private Image myBackgroundImage;
    private int myXRight;
    private int myYTop;
    private int myXLeft;
    private int myYBottom;

    /**
     * Creates a new movable background image
     * 
     * @param backgroundImage Background image.
     * @param drawWidth Width to be displayed at any one time.
     * @param drawHeight Height to be displayed at any one time. 
     * @param startX X position to start at on background image.
     * @param startY Y position to start at on background image.
     */
    public Background (Image backgroundImage, int drawWidth,
            int drawHeight, int startX, int startY) {
        myBackgroundImage = backgroundImage;
        myDrawWidth = drawWidth;
        myDrawHeight = drawHeight;
        ourDrawX = startX;
        ourDrawY = startY;

    }

    /**
     * Move the background horizontally by specified pixels.
     * @param pixels Pixels to move horizontally.
     */
    public void moveBackgroundHorizontal (int pixels) {
        ourDrawX += pixels;
    }

    /**
     * Move the background vertically by the specified pixels
     * @param pixels Pixels to move vertically.
     */
    public void moveBackgroundVertical (int pixels) {
        ourDrawY += pixels;
    }

    /**
     * 
     * @param p move the background the the specified center point
     */
    public void setDrawCenter (Point p) {
        ourDrawX = (int) (p.getX() - myDrawWidth / 2);
        ourDrawY = (int) (p.getY() - myDrawHeight / 2);
    }

    /**
     * 
     * @return the amount the background is moved from the absolute top
     */
    public int getYOffset () {
        return ourDrawY;
    }

    /**
     * 
     * @return the amount the background is moved from the absolute left
     */
    public int getXOffset () {
        return ourDrawX;
    }

    /**
     * @param trackSprite  Override to track a certain sprite etc or have automatic movement.
     */
    public abstract void update (Sprite trackSprite);

    /**
     * Override to track a certain sprite etc or have automatic movement.
     */
    public abstract void updateSprite();

    /**
     * Paints the background.
     * @param pen Graphics to paint with.
     */
    public void paint (Graphics2D pen) {

        adjustDrawingBounds();
        pen.drawImage(myBackgroundImage, 0, 0, myDrawWidth, myDrawHeight, myXLeft, myYTop, myXRight,
                myYBottom, null);
    }

    private void adjustDrawingBounds () {
        myYTop = (int) ourDrawY;
        myYBottom = (int) (ourDrawY + myDrawHeight);
        myXLeft = (int) ourDrawX;
        myXRight = (int) (ourDrawX + myDrawWidth);

        if (myYBottom > getGameHeight()) {
            myYBottom = getGameHeight();
            myYTop = getGameHeight() - myDrawHeight;
        }
        if (myYTop < 0) {
            myYTop = 0;
            myYBottom = myDrawHeight;
        }

        if (myXRight > getGameWidth()) {

            myXRight = getGameWidth();
            myXLeft = getGameWidth() - myDrawWidth;
        }
        if (myXLeft < 0) {
            myXLeft = 0;
            myXRight = myDrawWidth;

        }
        ourDrawY = myYTop;
        ourDrawX = myXLeft;
    }

    /**
     * 
     * @return returns the height of the image of the used for the background.
     *         This is the total game height.
     */
    public int getGameHeight () {
        return myBackgroundImage.getHeight(null);
    }

    /**
     * 
     * @return returns the width of the image used for the background. This the
     *         total game width;
     */
    public int getGameWidth () {
        return myBackgroundImage.getWidth(null);
    }

    /**
     * Transform a point for relative drawing based the current background position.
     * @param point point in the game coordinate space
     * @return a point in the relative drawing space
     */
    public static Point transformPoint (Point point) {
        return new Point((int)(point.getX() - ourDrawX), (int)(point.getY() - ourDrawY));
    }


}
